<?php
namespace Solle\PcbMessage;

use App\Models\SystemOptions;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Utils\SystemVisitor;
use PcbMessage AS PcbMessageFacade;

class PcbMessage
{
    const MESSAGE_OBJECT_TYPE_PRODUCT   = "product";
    const MESSAGE_OBJECT_TYPE_PAY_ORDER = "pay_order";
    const MESSAGE_OBJECT_TYPE_AFTER_SALES = "aftersales";
    const MESSAGE_TYPE_FEEDBACK         = 1;

    public function createFeedbackUrl($object_type,$object_id,$user_id,$user = null,$admin_id = 0,$admin = null): string
    {
        if(empty($admin_id)){
            SystemOptions::getCustomerByRandom($admin_id,$admin);
        }
        $feedback_session = md5(sprintf("type:%s,id:%d",$object_type,$object_id));
        $data = array(
            "object_type"   => $object_type,
            "object_id"     => $object_id,
            "admin_id"      => $admin_id,
            "admin"         => $admin ?: (DB::table("pcb_admin")->where("id",$admin_id)->value("nickname") ?: ""),
            "user_id"       => $user_id,
            "user"          => $user ?: (DB::table("pcb_accounts")->where("id",$user_id)->value("identity") ?: ""),
            "current"       => SystemVisitor::getId(),
            "role"          => SystemVisitor::getRole(),
        );
        $key = Crypt::encryptString(json_encode($data));
        return sprintf("/message/chat?session=%s&key=%s",$feedback_session,$key);
    }

    public function parseFeedbackKey($key){
        if(empty($key)){
            return [];
        }
        $data = Crypt::decryptString($key);
        $data = json_decode($data,true);
        if(!empty($data)){
            if($data["role"] == SystemVisitor::ADMIN_ROLE){
                SystemVisitor::setAdmin($data["current"]);
            }
            if($data["role"] == SystemVisitor::USER_ROLE){
                SystemVisitor::setUser($data["current"]);
            }
        }
        return $data;
    }

    public function sendMessage($type,$object,$params){
        $message = array();
        $message["type"] = $type;
        $message["object_type"] = $object["object_type"];
        $message["object_id"]   = $object["object_id"];
        $message["session"]     = $params["session"];
        if($object["role"] === SystemVisitor::ADMIN_ROLE){
            $message["sender"]          = $object["admin"] ?: "";
            $message["sender_id"]       = $object["admin_id"];
            $message["is_admin_sender"] = 1;
            $message["receiver"]        = $object["user"];
            $message["receiver_id"]     = $object["user_id"];
        }elseif ($object["role"] === SystemVisitor::USER_ROLE){
            $message["sender"]          = $object["user"];
            $message["sender_id"]       = $object["user_id"];
            $message["is_admin_receiver"] = 1;
            $message["receiver"]        = $object["admin"];
            $message["receiver_id"]     = $object["admin_id"];
        }else{
            throw new \Exception("illegitimate message");
        }
        unset($params["session"]);
        $message["content"]      = json_encode($params);
        $message["create_time"]  = time();
        $id = DB::table("pcb_message")->insertGetId($message);
        if($id){
            MessagePushRecord::record($message["session"],SystemVisitor::getRole(),SystemVisitor::getId(),$id,time());
        }
        return $id;
    }

    public function getMessageList($product_no,$unread,$user_id,$is_admin,$page,$limit){
        $handle = DB::table("pcb_message")
            ->join("pcb_order","pcb_order.id","=","pcb_message.object_id")
            ->where("pcb_message.receiver_id","=",$user_id)
            ->where("pcb_message.is_admin_receiver","=",$is_admin ? 1 : 0)
            ->where("pcb_message.type","=",self::MESSAGE_TYPE_FEEDBACK)
            ->where("pcb_order.is_del","=",0);
        if($product_no){
            $handle->where("pcb_order.product_no","LIKE","%{$product_no}%");
        }
        if($unread){
            $handle->where("pcb_message.is_read","=",0);
        }
        $groupResult = $handle->groupBy("pcb_message.session")
            ->selectRaw("MAX(pcb_message.id) as id,group_concat(any_value(pcb_message.is_read)) AS is_read,count(pcb_message.id) AS total,any_value(pcb_order.product_no) AS product_no,max(pcb_message.create_time) AS last_time
	,min(pcb_message.create_time) AS first_time")
            ->get();
        if(!empty($groupResult)){
            $idArr  = [];
            $r      = [];
            foreach($groupResult as $item){
                $idArr[] = $item->id;
                $r[$item->id] = array(
                    "unread" => strpos($item->is_read,"0") !== false,
                    "total"  => $item->total,
                    "product_no" => $item->product_no,
                    "last_time" => $item->last_time,
                    "first_time" => $item->first_time,
                );
            }
            $count = count($idArr);
            $list = DB::table("pcb_message")
                ->whereIn("id",array_unique($idArr))
                ->orderByDesc("create_time")
                ->skip(($page-1)*$limit)->take($limit)->get();
            if(!empty($list)){
                foreach($list as &$l){
                    $l->detail_url = PcbMessageFacade::createFeedbackUrl(
                        $l->object_type,
                        $l->object_id,
                        $is_admin ? $l->sender_id : $l->receiver_id,
                        $is_admin ? $l->sender : $l->receiver,
                        $is_admin ? $l->receiver_id : $l->sender_id,
                        $is_admin ? $l->receiver : $l->sender,
                    );
                    $l->detail_url = env("APP_URL") . $l->detail_url;
                    $l->unread  = $r[$l->id]["unread"] ? 1 : 0;
                    $l->total   = $r[$l->id]["total"];
                    $l->last_time = $r[$l->id]["last_time"];
                    $l->first_time = $r[$l->id]["first_time"];
                    $l->product_no = $r[$l->id]["product_no"];
                    $content    = json_decode($l->content,true);
                    $l->content = "";
                    if(!empty($content)){
                        if($content["type"] === "text"){
                            $l->content = $content["content"];
                        }else if($content["type"] === "image"){
                            $l->content = "[Image]";
                        }else if($content["type"] === "file"){
                            $l->content = "[File]";
                        }
                    }
                }
            }
        }else{
            $count  = 0;
            $list   = [];
        }

        return compact("list","count");
    }

    public function readByAdmin($sessions,$admin_id){
        return DB::table("pcb_message")
            ->whereIn("session",$sessions)
            ->where("is_admin_receiver","=",1)
            ->where("receiver_id","=",$admin_id)
            ->where("is_read","=",0)
            ->update(["is_read" => 1]);
    }

    public function unreadCount($user_id,$is_admin){
        $count = DB::table("pcb_message")
            ->join("pcb_order","pcb_order.id","=","pcb_message.object_id")
            ->where("pcb_message.receiver_id","=",$user_id)
            ->where("pcb_message.is_admin_receiver","=",$is_admin ? 1 : 0)
            ->where("pcb_message.type","=",self::MESSAGE_TYPE_FEEDBACK)
            ->where("pcb_order.is_del","=",0)
            ->where("pcb_message.is_read","=",0)
            ->selectRaw("GROUP_CONCAT(DISTINCT `session`) AS session")
            ->first();
        if(empty($count)){
            return 0;
        }
        return count(array_unique(array_filter(explode(",",$count->session))));
    }

}
